var _ = require('lodash'),
    Q = require('q'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    assemblyRelationController = require('../../../Barcode/server/controllers/AssemblyRelation.server.controller'),
    bizRecordController = require('../../../Barcode/server/controllers/BizRecord.server.controller');

exports.getProductFlow = function(req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode;

    var productFlow = {};
    queryBarcodeMaster(barcode).then(function(info) {
        productFlow.basicInfo = info.basicInfo;
        productFlow.productParam = info.productParam;
        return queryBizRecords(info.barcodeMasterIds);
    }).then(function(bizRecords) {
        _.merge(productFlow.basicInfo, bizRecords.realDateTime);
        delete bizRecords.realDateTime;
        _.merge(productFlow, bizRecords);
        res.json({
            Data: productFlow,
            Error: null
        });
    }).catch(function(err) {
        res.json({
            Data: null,
            Error: err
        });
    })
    .done();
};

function queryBarcodeMaster(barcode) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function(err, barcodeMaster) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!barcodeMaster || barcodeMaster.BarcodeType != 0) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询物料错误';
            newErr.message = '无法识别的芯片，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        assemblyRelationController.findAssemblyRelations(barcodeMaster._id).then(function (results) {
            var barcodeMasterIds = [], 
                lastBarcodeMaster;
            if (!results) {
                barcodeMasterIds.push(barcodeMaster._id);
                lastBarcodeMaster = barcodeMaster;
            } else {
                _.forEach(results, function (result) {
                    barcodeMasterIds.push(result.AssemblyBarcode._id);
                });
                barcodeMasterIds.push(results[0].BarcodeMaster);
                lastBarcodeMaster = results[0].AssemblyBarcode;
            }
            var result = {
                barcodeMasterId: lastBarcodeMaster._id,
                Barcode: lastBarcodeMaster.Barcode,
                ItemMasterCode: lastBarcodeMaster.ItemMasterCode,
                OperationName: lastBarcodeMaster.OperationName,
                QCStatus: lastBarcodeMaster.QCStatus,
                MOLotNumber: lastBarcodeMaster.MOLotNumber,
                ShipLotNumber: lastBarcodeMaster.ShipLotNumber
            };
            if (lastBarcodeMaster.MO) {
                _.merge(result, {
                    MOCode: lastBarcodeMaster.MO.Code,
                    Customer: lastBarcodeMaster.MO.Customer,
                    StartDateTime: lastBarcodeMaster.MO.StartDateTime,
                    EndDateTime: lastBarcodeMaster.MO.EndDateTime
                });
            }
            if (lastBarcodeMaster.ItemMaster) {
                _.merge(result, {
                    ItemMasterName: lastBarcodeMaster.ItemMaster.ItemMasterName,
                    Specification: lastBarcodeMaster.ItemMaster.Specification,
                    ItemCategory: lastBarcodeMaster.ItemMaster.ItemCategory
                });
            }
            deferred.resolve({
                basicInfo: result,
                productParam: {
                    GripSize: lastBarcodeMaster.DescSeg1
                },
                barcodeMasterIds: barcodeMasterIds
            });
        }, function (err) {
            deferred.reject(err);
        });
    });

    return deferred.promise;
}

function queryBizRecords(barcodeMasterIds) {
    var deferred = Q.defer();

    bizRecordController.findByBarcodeMaster(barcodeMasterIds, function(err, bizRecords) {
        if (err) {
            deferred.reject(err);
            return;
        }
        var results = {
            bizCatalog: [],
            bizRecords: {},
            realDateTime: {}
        };
        if (bizRecords.length >= 1) {
            results.realDateTime.RealStartDateTime = bizRecords[0].CollectDateTime;
            results.realDateTime.RealEndDateTime = bizRecords[bizRecords.length - 1].CollectDateTime;
        }
        var depUniqueId = 1000,
            lastResultRecord = {},
            workTime = 0,
            tmpRecord, lastCatalogId, lastWork, lastBizCollectTime;
        for (var i = 0, len = bizRecords.length; i < len; i++) {
            tmpRecord = bizRecords[i];
            if (!tmpRecord.WorkLocation || !tmpRecord.WorkLocation.Department) {
                continue;
            }
            if (tmpRecord.WorkLocation.Department._id !== lastCatalogId) {
                results.bizCatalog.push({
                    UniqueId: depUniqueId,
                    Code: tmpRecord.WorkLocation.Department.Code,
                    Name: tmpRecord.WorkLocation.Department.Name
                });
                results.bizRecords[depUniqueId] = [];

                lastCatalogId = tmpRecord.WorkLocation.Department._id;
                depUniqueId++;
            }
            if (tmpRecord.Work.toString() === lastWork) {
                workTime += ((tmpRecord.CollectDateTime - lastBizCollectTime) / 60000);
            } else {
                if (workTime > 0) {
                    lastResultRecord.WorkTime = workTime.toFixed(2);
                    workTime = 0;
                }
                lastResultRecord = {
                    CollectDateTime: tmpRecord.CollectDateTime,
                    TerminalName: tmpRecord.TerminalName,
                    WorkName: tmpRecord.WorkName,
                    WorkLocationName: tmpRecord.WorkLocationName,
                    Users: tmpRecord.Users
                };
                if (tmpRecord.QCType) {
                    lastResultRecord.QCStatus = tmpRecord.QCStatus;
                }
                lastResultRecord.QCFlag = tmpRecord.QCType ? true : false;
                results.bizRecords[depUniqueId - 1].push(lastResultRecord);
            }
            lastWork = tmpRecord.Work.toString();
            lastBizCollectTime = tmpRecord.CollectDateTime;
        }
        deferred.resolve(results);
    });

    return deferred.promise;
}